home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / pyshared / ufw / applications.py next >
Encoding:
Python Source  |  2008-10-08  |  6.2 KB  |  209 lines

  1. #
  2. # applications.py: common classes for ufw
  3. #
  4. # Copyright (C) 2008 Canonical Ltd.
  5. #
  6. #    This program is free software: you can redistribute it and/or modify
  7. #    it under the terms of the GNU General Public License version 3,
  8. #    as published by the Free Software Foundation.
  9. #
  10. #    This program is distributed in the hope that it will be useful,
  11. #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. #    GNU General Public License for more details.
  14. #
  15. #    You should have received a copy of the GNU General Public License
  16. #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. #
  18.  
  19. from ConfigParser import *
  20. import os
  21. import re
  22. from stat import *
  23. import ufw.util
  24. from ufw.util import debug, warn
  25. from ufw.common import UFWError
  26.  
  27. def get_profiles(dir):
  28.     '''Get profiles found in profiles database.  Returns dictionary with
  29.        profile name as key and tuples for fields
  30.     '''
  31.     if not os.path.isdir(dir):
  32.         err_msg = _("Profiles directory does not exist") % (dir)
  33.         raise UFWError("Error: profiles directory does not exist")
  34.  
  35.     max_size = 10 * 1024 * 1024  # 10MB
  36.     profiles = {}
  37.  
  38.     files = os.listdir(dir)
  39.     files.sort()
  40.  
  41.     total_size = 0
  42.     pat = re.compile(r'^\.')
  43.     for f in files:
  44.         abs = dir + "/" + f
  45.         if not os.path.isfile(abs):
  46.             continue
  47.  
  48.         if pat.search(f):
  49.             warn_msg = _("Skipping '%s': hidden file") % (f)
  50.             warn(warn_msg)
  51.             continue
  52.  
  53.         if f.endswith('.dpkg-new') or f.endswith('.dpkg-old') or \
  54.            f.endswith('.dpkg-dist') or f.endswith('.rpmnew') or \
  55.            f.endswith('.rpmsave') or f.endswith('~'):
  56.             debug("Skipping '%s'" % (f))
  57.             continue
  58.  
  59.     # Try to gracefully handle huge files for the user (no security
  60.         # benefit, just usability)
  61.         size = 0
  62.         try:
  63.             size = os.stat(abs)[ST_SIZE]
  64.         except Exception:
  65.             warn_msg = _("Skipping '%s': couldn't stat") % (f)
  66.             warn(warn_msg)
  67.             continue
  68.  
  69.         if size > max_size:
  70.             warn_msg = _("Skipping '%s': too big") % (f)
  71.             warn(warn_msg)
  72.             continue
  73.  
  74.         if total_size + size > max_size:
  75.             warn_msg = _("Skipping '%s': too many files read already") % (f)
  76.             warn(warn_msg)
  77.             continue
  78.  
  79.         total_size += size
  80.  
  81.         cdict = RawConfigParser()
  82.         try:
  83.             cdict.read(abs)
  84.         except Exception:
  85.             warn_msg = _("Skipping '%s': couldn't process") % (f)
  86.             warn(warn_msg)
  87.             continue
  88.  
  89.         # If multiple occurences of profile name, use the last one
  90.         for p in cdict.sections():
  91.             if len(p) > 64:
  92.                 warn_msg = _("Skipping '%s': name too long") % (p)
  93.                 warn(warn_msg)
  94.                 continue
  95.  
  96.             if not valid_profile_name(p):
  97.                 warn_msg = _("Skipping '%s': invalid name") % (p)
  98.                 warn(warn_msg)
  99.                 continue
  100.  
  101.             try:
  102.                 ufw.util.get_services_proto(p)
  103.                 warn_msg = _("Skipping '%s': also in /etc/services") % (p)
  104.                 warn(warn_msg)
  105.                 continue
  106.             except Exception:
  107.                 pass
  108.  
  109.             skip = False
  110.             for key, value in cdict.items(p):
  111.                 if len(key) > 64:
  112.                     warn_msg = _("Skipping '%s': field too long") % (p)
  113.                     warn(warn_msg)
  114.                     skip = True
  115.                     break
  116.                 if len(value) > 1024:
  117.                     warn_msg = _("Skipping '%s': value too long for '%s'") % \
  118.                                 (p, key)
  119.                     warn(warn_msg)
  120.                     skip = True
  121.                     break
  122.             if skip:
  123.                 continue
  124.  
  125.             if profiles.has_key(p):
  126.                 warn_msg = _("Duplicate profile '%s', using last found") % (p)
  127.                 warn(warn_msg)
  128.  
  129.             pdict = {}
  130.             for key, value in cdict.items(p):
  131.                 debug("add '%s' = '%s' to '%s'" % (key, value, p))
  132.                 pdict[key] = value
  133.  
  134.             profiles[p] = pdict
  135.  
  136.     return profiles
  137.  
  138. def valid_profile_name(name):
  139.     '''Only accept a limited set of characters for name'''
  140.     # Reserved profile name
  141.     if name == "all":
  142.         return False
  143.  
  144.     # Require first character be alpha, so we can avoid collisions with port
  145.     # numbers.
  146.     if re.match(r'^[a-zA-Z][a-zA-Z0-9 _\-\.+]*$', name):
  147.         return True
  148.     return False
  149.  
  150. def verify_profile(name, profile):
  151.     '''Make sure profile has everything needed'''
  152.     app_fields = ['title', 'description', 'ports']
  153.  
  154.     for f in app_fields:
  155.         if not profile.has_key(f):
  156.             err_msg = _("Profile '%s' missing required field '%s'") % \
  157.                         (name, f)
  158.             raise UFWError(err_msg)
  159.         elif not profile[f]:
  160.             err_msg = _("Profile '%s' has empty required field '%s'") % \
  161.                         (name, f)
  162.             raise UFWError(err_msg)
  163.  
  164.     ports = profile['ports'].split('|')
  165.     if len(ports) < 1:
  166.         err_msg = _("No ports found in profile '%s'") % (name)
  167.         return False
  168.  
  169.     try:
  170.         for p in ports:
  171.             (port, proto) = ufw.util.parse_port_proto(p)
  172.             # quick check if error in profile
  173.             #if not proto:
  174.             #    proto = "any"
  175.             rule = ufw.common.UFWRule("ACCEPT", proto, port)
  176.             debug(rule)
  177.     except Exception, e:
  178.         debug(e)
  179.         err_msg = _("Invalid ports in profile '%s'") % (name)
  180.         raise UFWError(err_msg)
  181.  
  182.     return True
  183.  
  184. def get_title(profile):
  185.     '''Retrieve the title from the profile'''
  186.     str = ""
  187.     field = 'title'
  188.     if profile.has_key(field) and profile[field]:
  189.         str = profile[field]
  190.     return str
  191.  
  192. def get_description(profile):
  193.     '''Retrieve the description from the profile'''
  194.     str = ""
  195.     field = 'description'
  196.     if profile.has_key(field) and profile[field]:
  197.         str = profile[field]
  198.     return str
  199.  
  200. def get_ports(profile):
  201.     '''Retrieve a list of ports from a profile'''
  202.     ports = []
  203.     field = 'ports'
  204.     if profile.has_key(field) and profile[field]:
  205.         ports = profile[field].split('|')
  206.  
  207.     return ports
  208.  
  209.